/*
 * Copyright (c) 2024. hallele, Inc All rights reserved.
 */

package cn.hallele.ms.starter.web.encoder;

import cn.hallele.infrastructure.metadata.constant.MsgCodeConst;
import cn.hallele.infrastructure.util.ObjectUtil;
import cn.hallele.infrastructure.util.SecurityUtil;
import cn.hallele.infrastructure.util.bean.RSA;
import cn.hallele.ms.infrastructure.plugin.safety.encoder.PasswordEncoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * hallele_mc_core
 *
 * @author anle5
 * @since 2024/11/10 15:41
 */
@Slf4j
public class RSAPasswordEncoder implements PasswordEncoder {
    private final RSA RSA;

    public RSAPasswordEncoder(String privateKey, String publicKey) {
        this.RSA = SecurityUtil.rsa(privateKey, publicKey);
    }

    /**
     * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
     * greater hash combined with an 8-byte or greater randomly generated salt.
     *
     * @param rawPassword 明文
     */
    @Override
    public String encode(CharSequence rawPassword) {
        return RSA.encryptHex(rawPassword.toString());
    }

    /**
     * 校验密码
     *
     * @param rawPassword     原始密码
     * @param encodedPassword 编码密码
     * @return 校验通过返回true，其他false
     */
    @Override
    public boolean matches(String rawPassword, String encodedPassword) {
        if (ObjectUtil.isBlank(rawPassword)) {
            log.error("Input password is null.");
            throw new java.lang.SecurityException(MsgCodeConst.SECURITY_ERROR);
        }
        if (StringUtils.isBlank(encodedPassword)) {
            log.error("Empty encoded password");
            throw new java.lang.SecurityException(MsgCodeConst.SECURITY_ERROR);
        }
        try {
            String clearRawPassword = this.RSA.decryptHex(rawPassword);
            String clearEncodedPassword = this.RSA.decryptHex(encodedPassword);
            return clearRawPassword.equals(clearEncodedPassword);
        } catch (Exception e) {
            log.error("Encryption or decryption exception", e);
            throw new SecurityException(MsgCodeConst.SECURITY_ERROR);
        }
    }
}
